package ch.uzh.ifi.seal.ssqa.metrics;

import ch.uzh.ifi.seal.ssqa.model.DiagramComponent;
import ch.uzh.ifi.seal.ssqa.model.DiagramComposite;
import ch.uzh.ifi.seal.ssqa.model.Source;
import ch.uzh.ifi.seal.ssqa.storage.IStorage;
import ch.uzh.ifi.seal.ssqa.storage.StorageResult;
import ch.uzh.ifi.seal.ssqa.storage.TeneoHibernateStorage;

public class LinesOfCodeMetric implements IMetric {

	private static final String identifier = "LOC";
	private static final String description = "Lines of Code";
	
	private double result = 0;

	private IStorage storage; 
	
	@Override
	public String getIdentifier() {
		return identifier;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public IMetric calculateResult(Object object) {
		double value = 0;
		this.storage = new TeneoHibernateStorage();
		if(object instanceof DiagramComponent){
			value += this.calculate((DiagramComponent)object);
		} else if (object instanceof Source){
			value += this.calculate((Source)object);
		}
		this.result = value;
		return this;
	}
	
	private double calculate(Source source){
		return source.getLineCount();
	}
	
	private double calculate(DiagramComponent component){
		double value = 0;
		if(component instanceof DiagramComposite){
			if(((DiagramComposite)component).getChildren() != null && ((DiagramComposite)component).getChildren().size()>0){
				for(DiagramComponent child : ((DiagramComposite)component).getChildren()){
					value += this.calculate(child);
				}
			}
		}
		try{
			StorageResult locResult = this.storage.executeUniqueSQLQuery("SELECT sum(linecount) " +
									"FROM `ssqa`.`component` " +
									"WHERE dtype = 'Source' AND diagrammapping = '" + component.getIdentifier() + "' ");
			Number loc = (Number) locResult.getResult();
			locResult.getSession().close();
			if(loc != null){
				value += loc.intValue();
			}
		} catch (Exception e){
			System.out.println("Could not calculate out "+this.getIdentifier());
		}
		return value;
	}

	@Override
	public double getResult() {
		return this.result;
	}
}
